package com.cdn.agent.component;

import com.baomidou.mybatisplus.core.MybatisParameterHandler;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.cdn.agent.IPrintLog;
import com.cdn.agent.enums.OrmType;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandlerRegistry;

import java.lang.reflect.Field;
import java.text.DateFormat;
import java.util.*;

/**
 * 蔡定努
 * 2024/08/27 13:28
 */
public class MybatisPlusLog extends IPrintLog {

    public MybatisPlusLog() {
        regist(this, OrmType.PLUS);
    }

    @Override
    public void printLog(Invocation invocation, long time) {
        StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
        BoundSql boundSql = statementHandler.getBoundSql();
        String method = getMethod(statementHandler);
        // 获取SQL语句
        String sql = boundSql.getSql();
        // 获取SQL参数
        List<Object> parameterValues = new ArrayList<>();
        ParameterHandler parameterHandler = statementHandler.getParameterHandler();
        Object parameterObject = parameterHandler.getParameterObject();
        if (parameterObject != null) {
            // 将参数转换为适当的类型并加入参数列表
            if (parameterObject instanceof List) {
                parameterValues.addAll((List<?>) parameterHandler.getParameterObject());
            } else if (parameterObject instanceof Object[]) {
                Object[] array = (Object[]) parameterHandler.getParameterObject();
                parameterValues.addAll(Arrays.asList(array));
            } else if (parameterObject instanceof MapperMethod.ParamMap) {
                HashMap<String, Object> ew = (HashMap) ((AbstractWrapper) ((MapperMethod.ParamMap) parameterObject).get("ew")).getParamNameValuePairs();
                ew.entrySet().stream()
                        .sorted(Map.Entry.comparingByKey())
                        .forEach(entry -> parameterValues.add(ew.get(entry.getKey())));
            } else {
                parameterValues.add(parameterObject);
            }
        }

        // 打印SQL和参数
        // System.out.println("Intercepted SQL: " + sql);
        // System.out.println("SQL Parameters: " + parameterValues);

        String replace = sql.replace("?", "%s");
        String format = String.format(replace, parameterValues.toArray());
        logs(time, format, method);
    }

    /**
     * @author 蔡定努
     */
    public String getMethod(StatementHandler statementHandler) {
        try {
            MybatisParameterHandler parameterHandler = (MybatisParameterHandler) statementHandler.getParameterHandler();
            Class<?> superclass = parameterHandler.getClass();
            Field mappedStatement = superclass.getDeclaredField("mappedStatement");
            mappedStatement.setAccessible(true);
            MappedStatement o = (MappedStatement) mappedStatement.get(parameterHandler);
            return o.getId();
        } catch (Exception ignored) {
            return "";
        }
    }


}
